package com.hy.app.point;

import android.content.Context;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;

import com.hy.app.R;
import com.hy.app.utils.OpenGlUtils;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * 映射缓冲对象使用
 */
public class MapperBufferRender implements GLSurfaceView.Renderer {
    private static final int VERTEX_POS_INDEX = 0;

    private static final int VERTEX_POS_SIZE = 3;

    private static final int VERTEX_STRIDE = VERTEX_POS_SIZE * 4;

    private final String vertexShader;

    private final String fragmentShader;

    private final FloatBuffer vertexBuffer;

    private int mProgramId;

    //顶点坐标
    private static final float[] vertexPoints = new float[]{
            0.0f, 0.5f, 0.0f,
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f
    };

    /**
     * 缓冲数组
     */
    private final int[] vboIds = new int[1];

    public MapperBufferRender(Context context) {
        vertexBuffer = ByteBuffer.allocateDirect(vertexPoints.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer();
        vertexBuffer.put(vertexPoints);
        vertexBuffer.position(0);

        vertexShader = OpenGlUtils.readRawShaderFile(context, R.raw.buffer_map_vertex_shader);
        fragmentShader = OpenGlUtils.readRawShaderFile(context, R.raw.buffer_map_fragment_shader);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        int vertexShaderId = OpenGlUtils.compileVertexShader(vertexShader);
        int fragmentShaderId = OpenGlUtils.compileFragmentShader(fragmentShader);
        mProgramId = OpenGlUtils.linkProgram(vertexShaderId, fragmentShaderId);

        //生成1个缓冲id
        GLES30.glGenBuffers(1, vboIds, 0);
        //向顶点坐标数据缓冲送入数据把顶点数组复制到缓冲中
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboIds[0]);
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertexPoints.length * 4, vertexBuffer, GLES30.GL_STATIC_DRAW);

        //映射缓冲区对象
        ByteBuffer byteBuffer = (ByteBuffer) GLES30.glMapBufferRange(GLES30.GL_ARRAY_BUFFER, 0,
                vertexPoints.length * 4, GLES30.GL_MAP_WRITE_BIT | GLES30.GL_MAP_INVALIDATE_BUFFER_BIT);
        //填充数据
        byteBuffer.order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertexPoints).position(0);

        //将顶点位置数据送入数据渲染管线
        GLES30.glVertexAttribPointer(VERTEX_POS_INDEX, VERTEX_POS_SIZE, GLES30.GL_FLOAT, false, VERTEX_STRIDE, 0);
        //启用顶点位置属性
        GLES30.glEnableVertexAttribArray(VERTEX_POS_INDEX);

        //解除映射
        GLES30.glUnmapBuffer(GLES30.GL_ARRAY_BUFFER);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES30.glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);

        //使用程序片段
        GLES30.glUseProgram(mProgramId);
        //绘制三角形
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, VERTEX_POS_INDEX, VERTEX_POS_SIZE);
        //解绑VBO
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);
    }
}
